#include "timerserver.h"
#include "protocol.h"

const int kBase = 1000;

const char *socketErrors[100] = {"ConnectionRefusedError",
                                 "RemoteHostClosedError",
                                 "HostNotFoundError",
                                 "SocketAccessError",
                                 "SocketResourceError",
                                 "SocketTimeoutError",
                                 "DatagramTooLargeError",
                                 "NetworkError",
                                 "AddressInUseError",
                                 "SocketAddressNotAvailableError",
                                 "UnsupportedSocketOperationError",
                                 "ProxyAuthenticationRequiredError",
                                 "SslHandshakeFailedError",
                                 "UnfinishedSocketOperationError",
                                 "ProxyConnectionRefusedError",
                                 "ProxyConnectionClosedError",
                                 "ProxyConnectionTimeoutError",
                                 "ProxyNotFoundError",
                                 "ProxyProtocolError",
                                 "UnknownSocketError"
                                };

TimerServer::TimerServer(QObject *parent) : QObject(parent),
    m_tcpserver(NULL),
    m_hearttime(5)
{
    m_userlist.clear();
    initserver();
}

void TimerServer::Broadcast(const QString &name,const QString &cmd,const QString &time)
{
    QString buf=name + "@"+cmd+"@" + time;
    QByteArray ba = buf.toLatin1();

    QMap<QString, QTcpSocket*>::Iterator iter;
    for(iter = m_userlist.begin(); iter != m_userlist.end(); ++iter)
    {
        sendData(iter.value(),ba);
    }
}

bool TimerServer::Start()
{
    //监听
    //if( !m_tcpserver->listen(QHostAddress::Any, kTimerPort) )
    if(!m_tcpserver->listen(QHostAddress::AnyIPv4, kTimerPort))
    {
        qDebug() << "listen error: " << m_tcpserver->errorString();
        return false;
    }
    else
    {
        qDebug() << "server start is ok!";
    }

    return true;
}

bool TimerServer::isStart()
{
    return m_tcpserver->isListening();
}

void TimerServer::Stop()
{
    m_tcpserver->close();
}

int TimerServer::clientNumber()
{
    return m_userlist.size();
}

void TimerServer::initserver()
{
    //启动一个tcpserver
    m_tcpserver = new QTcpServer(this);

    //来一个客户端连接，就会产生一个slot
    connect(m_tcpserver, SIGNAL(newConnection()), this, SLOT(handle_newConnection()));

    m_timer = new QTimer();
    connect(m_timer, SIGNAL(timeout()), this, SLOT(handle_updateUserList()));
}

void TimerServer::handle_newConnection()
{
    //得到每一个连接成功的客户段socket套接字
    QTcpSocket *newtcpsocket = m_tcpserver->nextPendingConnection();
    QMap<QString, QTcpSocket*>::Iterator iter;

    if( NULL == newtcpsocket )
    {
        qDebug() << "socket is error";
        return ;
    }

    QHostAddress address = newtcpsocket->peerAddress();
    QString clientIp = address.toString();

    if(clientIp.isEmpty())
    {
        qDebug()<<"new connection,but client ip is null";
        return ;
    }

    iter = m_userlist.find(clientIp);
    if(iter != m_userlist.end())
    {
        qDebug() << "ip reset: " << clientIp;
        QTcpSocket *oldSocket = iter.value();
        oldSocket->close();
        m_userlist[clientIp]=newtcpsocket;
    }
    else
    {
        qDebug() << "new user join it's ip: " << clientIp;
        m_userlist.insert(clientIp, newtcpsocket);        
    }
    connect(newtcpsocket, SIGNAL(readyRead()), this, SLOT(handle_readyRead()));
    connect(newtcpsocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(handle_error(QAbstractSocket::SocketError)));

    startHeart();
}

void TimerServer::startHeart()
{
    int socketcount = m_userlist.size();

    if( socketcount > 0)
    {
        m_timer->start(m_hearttime * kBase);
    }
    else
    {
        m_timer->stop();
    }
}

void TimerServer::handle_updateUserList()
{
    if(m_userlist.size() == 0)
    {
        m_timer->stop();
        return;
    }

    QMap<QString, QTcpSocket*>::Iterator iter;
    for(iter = m_userlist.begin(); iter != m_userlist.end(); )
    {
        QAbstractSocket::SocketState curstate = (*iter)->state();

        qDebug() <<*iter<<curstate;
        if( QAbstractSocket::UnconnectedState == curstate ||
           QAbstractSocket::ClosingState == curstate )
        {
            qDebug() << "erase close socket";
            iter = m_userlist.erase(iter);
        }
        else
        {
            ++iter;
        }
    }
}

void TimerServer::handle_readyRead()
{
    QTcpSocket *newtcpsocket = static_cast<QTcpSocket*>(this->sender());
    QString clientip = newtcpsocket->peerAddress().toString();

    QString recvbuf = newtcpsocket->readAll();
    if(recvbuf.length())
    {
        //QString msg = m_Name + "@" + kTimerCmdRegister + "@connected";
        QStringList sl = recvbuf.split("@");
        if(sl.size()==3)
        {
            if(sl[1] == kTimerCmdRegister)
            {
                if(sl[2] == "connected")
                {
                    emit upClient(CLI_NEW,sl[0],clientip);
                    QString atr = "server@";
                    atr += kTimerCmdAuthorization;
                    atr += "@valid";
                    sendData(newtcpsocket,atr.toLatin1());
                }
                else if(sl[2]=="exit")
                {
                    emit upClient(CLI_REMOVE,sl[0],clientip);
                    m_userlist.remove(clientip);
                }
            }
            else if(sl[1] == kTimerCmdDetect)
            {
                sendData(newtcpsocket,recvbuf.toLatin1());
            }
        }
    }

    qDebug() << "received user[" << clientip << "]text: " << recvbuf;
}

void TimerServer::handle_error(QAbstractSocket::SocketError errors)
{
    QString displays;

    QTcpSocket *newtcpsocket = static_cast<QTcpSocket*>(this->sender());
    QString clientip = newtcpsocket->peerAddress().toString();

    //发生错误时，服务端踢掉出错socket
    m_userlist.remove(newtcpsocket->peerAddress().toString());
    emit upClient(CLI_REMOVE,"",clientip);

    qDebug() << "user " << clientip << " is left..";

    if( errors == 1 )
    {
        return ;
    }
    else if( -1 == errors )
    {
        displays = socketErrors[19];
    }
    else
    {
        displays = socketErrors[errors];
    }

    emit upClient(ERR_MSG,displays,clientip);
}

void TimerServer::sendData(QTcpSocket *newtcpsocket, const QString &str)
{
    sendData(newtcpsocket,str.toLatin1());
}

void TimerServer::sendData(QTcpSocket *newtcpsocket, const QByteArray &data)
{
    int len = newtcpsocket->write(data);
    if( len > 0 )
    {
        //send ok
    }
}
